﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using MagicControls;
using MagicControls.Utilities;

namespace MagicControls
{
    public enum SplitterType
    {
        Vertical,
        Horizontal
    }

    public class Splitter : ControlBase
    {
        #region Child controls

        private readonly Rectangle splitterRect = new Rectangle();
        private readonly Rectangle movePositionRect = new Rectangle();

        #endregion

        #region Linked controls

        private FrameworkElement control1;
        private FrameworkElement control2;

        #endregion

        #region Public properties

        private string control1Name;
        private string control2Name;
        private SplitterType splitterType = MagicControls.SplitterType.Vertical;

        public string Control1Name
        {
            get { return control1Name; }
            set { control1Name = value; }
        }

        public string Control2Name
        {
            get { return control2Name; }
            set { control2Name = value; }
        }

        public string SplitterType
        {
            get { return splitterType.ToString(); }
            set { splitterType = (SplitterType) Enum.Parse(typeof(SplitterType), value, true); }
        }

        #endregion

        #region Fields

        private bool mousePressed = false;
        private Point clickedPoint;

        #endregion

        #region Overriden members


        protected override string ResourceName
        {
            get { return "MagicControls.XAML.Splitter.xaml"; }
        }


        #endregion

        #region Initialization members

        public Splitter()
        {
            Loaded += Splitter_Loaded;

            MouseEnter += Splitter_MouseEnter;
            MouseLeave += Splitter_MouseLeave;
            MouseLeftButtonDown += Splitter_MouseLeftButtonDown;
            MouseLeftButtonUp += Splitter_MouseLeftButtonUp;
            SizeChanged += Splitter_SizeChanged;

            splitterRect = (Rectangle)FindName("splitterRect");
        }

        private void Splitter_SizeChanged(object o, SizeChangedEventArg eventArg)
        {
            splitterRect.Height = Height;
            splitterRect.Width = Width;
        }

        private void Splitter_Loaded(object sender, EventArgs e)
        {

            if (splitterType == MagicControls.SplitterType.Vertical)
            {
                SetValue(Canvas.TopProperty, 0);
            }
            else
            {
                SetValue(Canvas.LeftProperty, 0);
            }

            CanvasBase parent = Parent as CanvasBase;

            if (parent != null)
            {
                if (splitterType == MagicControls.SplitterType.Vertical)
                {
                    Height = parent.Height;
                    Width = (double)GetValue(WidthProperty);
                }
                else
                {
                    Height = (double)GetValue(HeightProperty);
                    Width = parent.Width;
                }
                parent.SizeChanged += Parent_SizeChanged;

                FrameworkElement topElement = MCUtils.FindMainElement(parent);
                topElement.MouseMove += Splitter_MouseMove;
                topElement.MouseLeftButtonUp += Splitter_MouseLeftButtonUp;

                control1 = parent.FindName(control1Name) as FrameworkElement;
                control2 = parent.FindName(control2Name) as FrameworkElement;

                UpdateLinkedControlLayouts();
            } else 
                throw new IncorrectParentException(this, Parent as FrameworkElement, typeof (ControlBase));
        }

        #endregion

        #region Event Handlers

        private void Splitter_MouseMove(object sender, MouseEventArgs e)
        {
            if (mousePressed)
            {
                Point currentPosition = e.GetPosition(null);
                if (splitterType == MagicControls.SplitterType.Vertical)
                {
                    double deltaX = currentPosition.X - clickedPoint.X;
                    movePositionRect.SetValue(Canvas.LeftProperty, ((double)movePositionRect.GetValue(Canvas.LeftProperty)) + deltaX);
                }
                else
                {
                    double deltaY = currentPosition.Y - clickedPoint.Y;
                    movePositionRect.SetValue(Canvas.TopProperty, ((double)movePositionRect.GetValue(Canvas.TopProperty)) + deltaY);
                }
                clickedPoint = currentPosition;
            }
        }

        private void Splitter_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            if (mousePressed)
            {
                mousePressed = false;

                Canvas canvas = Parent as Canvas;
                canvas.Children.Remove(movePositionRect);

                Point currentPosition = e.GetPosition(null);
                if (splitterType == MagicControls.SplitterType.Vertical)
                {
                    Position = new Point(currentPosition.X, Position.Y);
                }
                else
                {
                    Position = new Point(Position.X, currentPosition.Y);
                }
                UpdateLinkedControlLayouts();
            }
        }

        private void Splitter_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            mousePressed = true;
            clickedPoint = e.GetPosition(null);

            movePositionRect.SetValue(Canvas.TopProperty, Position.Y);
            movePositionRect.SetValue(Canvas.LeftProperty, Position.X);
            movePositionRect.Height = Height;
            movePositionRect.Width = Width;
            SolidColorBrush brush = new SolidColorBrush(Colors.Black);
            brush.Opacity = 0.5;
            movePositionRect.Fill = brush;

            Canvas canvas = Parent as Canvas;
            canvas.Children.Add(movePositionRect);
        }

        private void Parent_SizeChanged(object o, SizeChangedEventArg eventArg)
        {
            if (splitterType == MagicControls.SplitterType.Vertical)
            {
                Height = eventArg.Height;
            } else
            {
                Width = eventArg.Width;
            }
            UpdateLinkedControlLayouts();
        }

        private void Splitter_MouseLeave(object sender, EventArgs e)
        {
            Cursor = Cursors.Default;
        }

        private void Splitter_MouseEnter(object sender, MouseEventArgs e)
        {
            Cursor = Cursors.Hand;
        }

        #endregion

        #region Heplers

        private void UpdateLinkedControlLayouts()
        {
            CanvasBase parent = Parent as CanvasBase;

            if (parent != null)
            {
                if (splitterType == MagicControls.SplitterType.Vertical)
                {
                    control1.SetValue(Canvas.TopProperty, 0);
                    control1.SetValue(Canvas.LeftProperty, 0);

                    double control1Width = Position.X;
                    double control1Height = parent.Height;

                    if (control1 is IMagicControl)
                    {
                        ((IMagicControl)control1).Width = control1Width;
                        ((IMagicControl)control1).Height = control1Height;
                    } else
                    {
                        control1.Width = control1Width;
                        control1.Height = control1Height;
                    }

                    control2.SetValue(Canvas.TopProperty, 0);
                    control2.SetValue(Canvas.LeftProperty, Position.X + Width);

                    double control2Width = parent.Width - (Position.X + Width);
                    if (control2Width < 0) control2Width = 0;
                    double control2Height = parent.Height;

                    if (control2 is IMagicControl)
                    {
                        ((IMagicControl)control2).Width = control2Width;
                        ((IMagicControl)control2).Height = control2Height;
                    }
                    else
                    {
                        control2.Width = control2Width;
                        control2.Height = control2Height;
                    }
                }
                else
                {
                    control1.SetValue(Canvas.TopProperty, 0);
                    control1.SetValue(Canvas.LeftProperty, 0);

                    double control1Width = parent.Width;
                    double control1Height = Position.Y;

                    if (control1 is IMagicControl)
                    {
                        ((IMagicControl)control1).Width = control1Width;
                        ((IMagicControl)control1).Height = control1Height;
                    }
                    else
                    {
                        control1.Width = control1Width;
                        control1.Height = control1Height;
                    }

                    control2.SetValue(Canvas.TopProperty, Position.Y + Height);
                    control2.SetValue(Canvas.LeftProperty, 0);

                    double control2Width = parent.Width;
                    double control2Height = parent.Height - (Position.Y + Height);
                    if (control2Height < 0) control2Height = 0;

                    if (control2 is IMagicControl)
                    {
                        ((IMagicControl)control2).Width = control2Width;
                        ((IMagicControl)control2).Height = control2Height;
                    }
                    else
                    {
                        control2.Width = control2Width;
                        control2.Height = control2Height;
                    }
                }
            }
        }


        #endregion
    }
}